package com.duowan.cms.rpst.tag;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.duowan.cms.common.repository.AbstractDomainObjectRepository;
import com.duowan.cms.common.repository.SQLParameterPair;
import com.duowan.cms.common.repository.SQLParameterPair.SQLOperateType;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.domain.tag.Tag;
import com.duowan.cms.domain.tag.rpst.TagRepository;
import com.duowan.cms.dto.tag.TagInfo;
import com.duowan.cms.dto.tag.TagSearchCriteria;

public class TagRepositoryImpl extends AbstractDomainObjectRepository<Tag, TagInfo, TagSearchCriteria> implements TagRepository {

    @Override
    protected Class<Tag> getDomainObjectClass() {
        return Tag.class;
    }
    
    @Override
    public String getTreeByChannelIdAndName(String channelId, String name) {
        
        Map<String, String> map = new HashMap<String, String>();
        map.put("channelId", channelId);
        map.put("name", name);
        return (String)queryObject(new SQLParameterPair(getPrefix() + ".getTreeByChannelIdAndName", map, SQLOperateType.SELECT_ONE));
    }

    @Override
    public void delete(Tag tag) {
        
        String prefix = getDomainObjectClass().getName();
        List<SQLParameterPair> list = new ArrayList<SQLParameterPair>();
        
        // 1.在list_db中查询出有该tag的文章
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("channelId", tag.getChannel().getId());
        map.put("tag", tag.getName());
        @SuppressWarnings("unchecked")
        List<Long> articleIds = (List<Long>)queryObject(new SQLParameterPair(prefix + ".delete-first", map, SQLOperateType.SELECT_LIST));
        // 2.删除tagtree中tag的记录
        list.add(new SQLParameterPair(prefix + ".delete-second", map, SQLOperateType.DELETE));
        // 3.更新list_db(deltet tag)
        list.add(new SQLParameterPair(prefix + ".delete-third", map, SQLOperateType.DELETE));
        // 4.更新article_db
        if(null != articleIds && !articleIds.isEmpty()){
            map.put("_tag", "," + tag.getName());
            map.put("articleIds", articleIds);
            list.add(new SQLParameterPair(prefix + ".delete-fourth", map, SQLOperateType.UPDATE));
        }
        updateList(list);
    }

    @Override
    public void updateTemplateName(String channelId, String tagName, String alias) {
        //
    }

    @Override
    public Tag getByChannelIdAndName(String channelId, String name) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("channelId", channelId);
        map.put("name", name);

        return selectOne(getDomainObjectClass().getName() + ".getByChannelIdAndName", map);

    }

    @Override
    public List<TagInfo> getDescendant(String channelId, String parent) {

        List<TagInfo> tag_list = getAllTagsInChannel(channelId);
        Map<String, List<TagInfo>> map = new HashMap<String, List<TagInfo>>();
        for (TagInfo tagInfo : tag_list) {
            // 将list中tag信息按(标签名,标签的子标签信息列表)存放到map中
            map.put(tagInfo.getName(), getSon(tagInfo.getName(), tag_list));
        }

        List<TagInfo> descendant = getDescendant(getSon(parent, tag_list), map);
        return descendant;
    }

    /**
     * 筛选：从list中选取TagInfo的parentName为parent的列表。
     * @author yzq
     * @param parent
     * @param list
     * @return
     */
    private List<TagInfo> getSon(String parent, List<TagInfo> list) {

        List<TagInfo> sonList = new ArrayList<TagInfo>();

        for (TagInfo tag : list) {
            if (tag.getParentName().equals(parent)) {
                sonList.add(tag);
            }
        }
        return sonList;
    }

    /**
     * 从map中查询出list列表中每一个元素的后代
     * @param list
     * @param map
     * @return
     */
    private List<TagInfo> getDescendant(List<TagInfo> list, Map<String, List<TagInfo>> map) {

        List<TagInfo> tags = new ArrayList<TagInfo>();

        for (TagInfo tag : list) {
            tags.add(tag);
            if (!map.get(tag.getName()).isEmpty()) {
                tags.addAll(getDescendant(map.get(tag.getName()), map));
            }
        }

        return tags;
    }

    @Override
    public List<TagInfo> getDescendantIncludeSelf(String channelId, String parent) {
        if (StringUtil.isEmpty(parent))
            return getAllTagsInChannel(channelId);
        Tag tag = getByChannelIdAndName(channelId, parent);
        if (null == tag)
            return null;
        Map<String, String> map = new HashMap<String, String>();
        map.put("channelId", channelId);
        map.put("tagtree", tag.getTree());
        return selectList(getDomainObjectClass().getName() + ".getDescendantIncludeSelf", map);
    }

    @Override
    public List<TagInfo> getChildren(String channelId, String parent) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("channelId", channelId);
        map.put("parent", parent);

        return selectList(getDomainObjectClass().getName() + ".getChildren", map);
    }

    @Override
    public List<TagInfo> getChildrenExcludeSpecial(String channelId, String parent) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("channelId", channelId);
        map.put("parent", parent);

        return selectList(getDomainObjectClass().getName() + ".getChildrenExcludeSpecial", map);
    }

    @Override
    public List<TagInfo> getTagsExcludeSpecial(String channelId) {
        return selectList(getDomainObjectClass().getName() + ".getTagsExcludeSpecial", channelId);
    }

    @Override
    public List<TagInfo> getSpecialTags(String channelId) {
        return selectList(getDomainObjectClass().getName() + ".getSpecialTags", channelId);
    }

    @Override
    public List<TagInfo> getAllTagsInChannel(String channelId) {
        return selectList(getDomainObjectClass().getName() + ".getAllTagsInChannel", channelId);
    }

    @Override
    public void moveTag(Tag srcTag, Tag destTag) {

        if (null == srcTag || null == destTag)
            return;
        String channelId = srcTag.getChannel().getId();
        if (StringUtil.isEmpty(channelId) || !channelId.equals(destTag.getChannel().getId()))
            return;

        // 新的标签树
        String tagTree = dealTagtree(destTag.getTree(), srcTag.getName());

        Map<String, String> map1 = new HashMap<String, String>();
        map1.put("parentTag", destTag.getName());
        map1.put("tagTree", tagTree);
        map1.put("channelId", channelId);
        map1.put("tagName", srcTag.getName());

        Map<String, String> map2 = new HashMap<String, String>();
        map2.put("oldtree", srcTag.getTree());
        map2.put("newtree", tagTree);
        map2.put("channelId", channelId);
        //map2.put("tagName", srcTag.getName());

        List<SQLParameterPair> list = new ArrayList<SQLParameterPair>();
        // 1.更新自身数据
        list.add(new SQLParameterPair(getDomainObjectClass().getName() + ".moveTag-1", map1, SQLOperateType.UPDATE));
        // 2.更新子孙数据
        list.add(new SQLParameterPair(getDomainObjectClass().getName() + ".moveTag-2", map2, SQLOperateType.UPDATE));

        updateList(list);
    }

    @Override
    public void updateTagName(String channelId, String oldTagName, String newTagName) {

        Map<String, String> map = new HashMap<String, String>();
        map.put("channelId", channelId);
        map.put("oldTagName", oldTagName);
        map.put("newTagName", newTagName);

        Map<String, String> map3 = new HashMap<String, String>();
        map3.put("channelId", channelId);
        map3.put("oldTagName", "," + oldTagName + ",");
        map3.put("newTagName", "," + newTagName + ",");

        List<SQLParameterPair> list = new ArrayList<SQLParameterPair>();
        String prefix = getDomainObjectClass().getName();
        // 1.修改自身
        list.add(new SQLParameterPair(prefix + ".updateTagName-1", map, SQLOperateType.UPDATE));
        // 2.若被修改的标签有子孙Tag，则 修改子孙Tag的parenttag
        list.add(new SQLParameterPair(prefix + ".updateTagName-2", map, SQLOperateType.UPDATE));
        // 3.修改所有与被修改标签相关联的tagtree
        list.add(new SQLParameterPair(prefix + ".updateTagName-3", map3, SQLOperateType.UPDATE));
        updateList(list);
    }

    private String dealTagtree(String tagtree, String tag) {
        if (StringUtil.isEmpty(tag))
            return tagtree;
        if (StringUtil.isEmpty(tagtree))
            return "," + tag + ",";
        return tagtree + tag + ",";
    }

}
